package org.zdc.pivot.wtk;
import nme.display.Graphics;
import org.zdc.core.IllegalArgumentException;
import org.zdc.core.UnsupportedOperationException;
import org.zdc.pivot.wtk.FocusTraversalDirection;
import org.zdc.pivot.wtk.listener.ListenerList;
import org.zdc.pivot.wtk.listener.IContainerListener;
import org.zdc.pivot.wtk.listener.IContainerMouseListener;
using Lambda;

class Container extends Component
{
	private var components:Array<Component>;
	private var focusTraversalPolicy:IFocusTraversalPolicy;
	private var mouseOverComponent:Component;
    private var isMouseDown:Bool;
    private var mouseDownComponent:Component;
    private var mouseDownTime:Int;
    private var mouseClickCount:Int;
    private var mouseClickConsumed:Bool;
	private var doubleBuffering:Bool;
	private var doubleBufferImage:Dynamic;
	private var doubleBufferedRepaintRequired:Bool;
	private var containerListeners:ContainerListenerList;
	private var containerMouseListeners:ContainerMouseListenerList;
	
	
	public function new() 
	{
		components = new Array<Component>();
		isMouseDown = false;
		mouseDownComponent = null;
		mouseDownTime = 0;
		mouseClickCount = 0;
		mouseClickConsumed = false;
		doubleBufferImage = false;
		doubleBufferedRepaintRequired = false;
		containerListeners = new ContainerListenerList();
		containerMouseListeners = new ContainerMouseListenerList();
		
		super();
	}
	
	/**
	 * 
	 * @param	c
	 */
	public function add(c:Component):Int {
		var index:Int = getLength();
		insert(c, index);
		return index;
	}
	
	/**
	 * 
	 * @param	c
	 * @param	index
	 */
	public function insert(c:Component, index:Int):Void {
		c.setParent(this);
		components.insert(index, c);
		
		repaint(c.getDecoratedBounds());
		
		invalidate();
		
		containerListeners.componentInserted(this, index);
	}
	
	/**
	 * 
	 * @param	index
	 * @param	c
	 * @return
	 */
	public function update(index:Int, c:Component):Component {
		throw new UnsupportedOperationException();
		
		return null;
	}
	
	/**
	 * 删除组件
	 * @param	c
	 * @return
	 */
	public function remove(c:Component):Int {
		var index:Int = indexOf(c);
		if (index != -1) {
			c.setParent(null);
			removeChild(c);
			
			repaint();
		}
		components.remove(c);
		return index;
	}
	
	/**
	 * 删除多个组件
	 * @param	index
	 * @param	count
	 */
	public function multiRemove(index:Int, count:Int):Array<Component> {
		var arr:Array<Component> = components.splice(index, count);
		
		for (c in arr) {
			remove(c);
		}
		
		return arr;
	}
	
	/**
	 * 删除所有组件
	 * @return
	 */
	public function removeAll():Array<Component> {
		return multiRemove(0, components.length);
	}
	
	/**
	 * 从组件队列中移动一个组件
	 * @param	from
	 * @param	to
	 */
	public function move(from:Int, to:Int):Void {
		if (from != to) {
			//....
			
			//重绘
			repaint();
			
			containerListeners.componentMoved(this, from, to);
		}
	}
	
	/**
	 * 获取指定位置的组件
	 * @param	index
	 * @return
	 */
	public function get(index:Int):Component {
		var c:Component = components[index];
		return c;
	}
	
	/**
	 * 获取组件索引
	 * @param	c
	 * @return
	 */
	public function indexOf(c:Component):Int {
		return components.indexOf(c);
	}
	
	/**
	 * 获取组件数量
	 * @return
	 */
	public function getLength():Int {
		return components.length;
	}
	
	/**
	 * 
	 * @return
	 */
	public function iterator():Iterator<Component> {
		return components.iterator();
	}
	
	/**
	 * 
	 * @param	parent
	 */
	override public function setParent(parent:Container):Void {
		if (cparent == null &&
			containsFocus()) {
			Component.clearFocus();
		}
		
		super.setParent(parent);
	}
	
	/**
	 * 获取坐标位置的组件
	 * @param	x
	 * @param	y
	 * @return
	 */
	public function getComponentAt(x:Float, y:Float):Component {
		return null;
	}
	
	/**
	 * 获取坐标位置的后代
	 * @param	x
	 * @param	y
	 * @return
	 */
	public function getDescendantAt(x:Float, y:Float):Component {
		return null;
	}
	
	/**
	 * 获取命名的组件
	 * @param	name
	 * @return
	 */
	public function getNamedComponent(name:String):Component {
		if (name == null) {
            throw new IllegalArgumentException();
        }
		
		return untyped this.getChildByName(name);
	}
	
	/**
	 * 似乎没意义
	 * @param	visible
	 */
	//override public function setVisible(visible:Bool):Void {
		//
	//}
	
	/**
	 *	布局
	 */
	override public function layout():Void {
		super.layout();
		
		for (c in components) {
			c.validate();
		}
	}
	
	override public function paint():Void {
		
	}
	
	/**
	 * 检测容器是否组件的祖先，组件被认为是自己的祖先
	 * @param	c
	 * @return
	 */
	public function isAncestor(c:Component):Bool {
		var ancestor:Bool = false;
		var p:Component = c;
		
		while (p != null) {
			if (p == this) {
				ancestor = true;
				break;
			}
			
			p = p.getParent();
		}
		
		return ancestor;
	}
	
	/**
	 * 似乎没意义
	 * @return
	 */
	//override public function requestFocus():Bool {
		//return false;
	//}
	
	/**
	 * 传递焦点，暂时用不着
	 * @param	c
	 * @param	direction
	 * @return
	 */
	public function transferFocus(c:Component, direction:FocusTraversalDirection):Component {
		return null;
	}
	
	/**
	 * 获取焦点遍历测试
	 * @return
	 */
	public function getFocusTraversalPolicy():IFocusTraversalPolicy {
		return this.focusTraversalPolicy;
	}
	
	/**
	 * 设置焦点遍历测试
	 * @param	focusTraversalPolicy
	 */
	public function setFocusTraversalPolicy(focusTraversalPolicy:IFocusTraversalPolicy):Void {
		
	}
	
	/**
	 * 是否拥有焦点
	 * @return
	 */
	public function containsFocus():Bool {
		if (stage != null) {
			return stage.focus == this;
		}
		return false;
	}
	
	/**
	 * 
	 * @param	descendant
	 */
	public function descendantAdded(descendant:Component):Void {
		var parent:Container = getParent();
		
		if (parent != null) {
			parent.descendantAdded(descendant);
		}
	}
	
	/**
	 * 
	 * @param	descendant
	 */
	public function descendantRemoved(descendant:Component):Void {
		var parent:Container = getParent();
		
		if (parent != null) {
			parent.descendantRemoved(descendant);
		}
	}
	
	/**
	 * 
	 * @param	descendant
	 * @param	previousFocusedComponent
	 */
	public function descendantGainedFocus(descendant:Component, previousFocusedComponent:Component):Void {
		
	}
	
	/**
	 * 
	 * @param	descendant
	 */
	public function descendantLostFocus(descendant:Component):Void {
		
	}
	
	/**
	 * 加载数据到子组件
	 * @param	context
	 */
	override public function load(context:Dynamic):Void {
		for (c in components) {
			c.load(context);
		}
	}
	
	/**
	 * 加载数据到子组件
	 * @param	context
	 */
	override public function store(context:Dynamic):Void {
		for (c in components) {
			c.store(context);
		}
	}
	
	/**
	 * 清除
	 */
	override public function clear():Void {
		for (c in components) {
			c.clear();
		}
	}
	
	/**
	 * 鼠标移动
	 * @param	x
	 * @param	y
	 * @return
	 */
	override public function mouseMove(x:Float, y:Float):Bool {
		return false;
	}
	
	/**
	 * 
	 */
	override public function mouseOut():Void {
		
	}
	
	/**
	 * 
	 * @param	button
	 * @param	x
	 * @param	y
	 * @return
	 */
	override public function mouseDown(button:MouseButton, x:Float, y:Float):Bool {
		return false;
	}
	
	/**
	 * 
	 * @param	button
	 * @param	x
	 * @param	y
	 * @return
	 */
	override public function mouseUp(button:MouseButton, x:Float, y:Float):Bool {
		return false;
	}
	
	/**
	 * 
	 * @param	button
	 * @param	x
	 * @param	y
	 * @param	count
	 * @return
	 */
	override public function mouseClick(button:MouseButton, x:Float, y:Float, count:Int):Bool {
		return false;
	}
	
	/**
	 * 
	 * @param	scrollType
	 * @param	scrollAmount
	 * @param	wheelRotation
	 * @param	x
	 * @param	y
	 * @return
	 */
	override public function mouseWheel(scrollType:MouseScrollType, scrollAmount:Int, wheelRotation:Int, x:Float, y:Float):Bool {
		return false;
	}
	
	/**
	 * 
	 */
	//override public function invalidate():Void {
		//
	//}
	
	/**
	 * 
	 * @param	?area
	 * @param	?immediate
	 */
	//override public function repaint(?area:Bounds = null, ?immediate:Bool = false):Void {
		//
	//}
	
	/**
	 * 容器侦听列表
	 * @return
	 */
	public function getContainerListeners():ListenerList<IContainerListener> {
		return containerListeners;
	}
	
	/**
	 * 容器鼠标侦听列表
	 * @return
	 */
	public function getContainerMouseListeners():ListenerList<IContainerMouseListener> {
		return containerMouseListeners;
	}
}

import org.zdc.pivot.wtk.listener.WTKListenerList;
import org.zdc.pivot.wtk.listener.IContainerListener;
class ContainerListenerList extends WTKListenerList<IContainerListener>, implements IContainerListener {
	/**
	 * 当组件加入容器时
	 * @param	container
	 * @param	index
	 */
	public function componentInserted(container:Container, index:Int):Void {
		for (l in this) {
			l.componentInserted(container, index);
		}
	}
	
	/**
	 * 当组件被删除时
	 * @param	container
	 * @param	index
	 * @param	removed
	 */
	public function componentsRemoved(container:Container, index:Int, removed:Array<Component>):Void {
		for (l in this) {
			l.componentsRemoved(container, index, removed);
		}
	}
	
	/**
	 * 当组件被删除时
	 * @param	container
	 * @param	index
	 * @param	removed
	 */
	public function componentMoved(container:Container, from:Float, to:Float):Void {
		for (l in this) {
			l.componentMoved(container, from, to);
		}
	}
	
	/**
	 * 当组件焦点遍历改变时
	 * @param	container
	 * @param	from
	 * @param	to
	 */
	public function focusTraversalPolicyChanged(container:Container, previousFocusTraversalPolicy:IFocusTraversalPolicy):Void {
		for (l in this) {
			l.focusTraversalPolicyChanged(container, previousFocusTraversalPolicy);
		}
	}
}

import org.zdc.pivot.wtk.listener.WTKListenerList;
import org.zdc.pivot.wtk.listener.IContainerMouseListener;
class ContainerMouseListenerList extends WTKListenerList<IContainerMouseListener>, implements IContainerMouseListener {
	/**
	 * 鼠标移动
	 * @param	con
	 * @param	x
	 * @param	y
	 * @return
	 */
	public function mouseMove(con:Container, x:Float, y:Float):Bool {
		var res:Bool = false;
		for (l in this) {
			res = l.mouseMove(con, x, y) || res;
		}
		return res;
	}
	
	/**
	 * 鼠标按下
	 * @param	con
	 * @param	button
	 * @param	x
	 * @param	y
	 * @return
	 */
	public function mouseDown(con:Container, button:MouseButton, x:Float, y:Float):Bool {
		var res:Bool = false;
		for (l in this) {
			res = l.mouseDown(con, button, x, y) || res;
		}
		return res;
	}
	
	/**
	 * 鼠标弹起
	 * @param	con
	 * @param	button
	 * @param	x
	 * @param	y
	 * @return
	 */
	public function mouseUp(con:Container, button:MouseButton, x:Float, y:Float):Bool {
		var res:Bool = false;
		for (l in this) {
			res = l.mouseUp(con, button, x, y) || res;
		}
		return res;
	}
	
	/**
	 * 鼠标滑轮
	 * @param	con
	 * @param	scrollType
	 * @param	scrollAmount
	 * @param	wheelRotation
	 * @param	x
	 * @param	y
	 * @return
	 */
	public function mouseWheel(con:Container, scrollType:MouseScrollType, scrollAmount:Int, wheelRotation:Int, x:Float, y:Float):Bool {
		var res:Bool = false;
		for (l in this) {
			res = l.mouseWheel(con, scrollType, scrollAmount, wheelRotation, x, y) || res;
		}
		return res;
	}
}